package com.liyunc.demo.bundle.user.org.service.imlp;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.liyunc.demo.bundle.user.org.model.dto.input.PersonManagerRegisterRequestDto;
import com.liyunc.demo.bundle.user.org.model.dto.input.PersonResetPasswordRequestDto;
import com.liyunc.demo.bundle.user.org.model.dto.input.PersonUpdateRequestDto;
import com.liyunc.demo.bundle.user.org.model.dto.output.PersonRegisterResponseDto;
import com.liyunc.demo.bundle.user.org.utils.converter.UserPersonConverter;
import com.liyunc.demo.bundle.user.org.model.dto.input.PersonRegisterRequestDto;
import com.liyunc.demo.bundle.user.org.model.dto.output.UserPersonalAccountDto;
import com.liyunc.demo.bundle.user.org.dao.mapper.UserPersonalAccountMapper;
import com.liyunc.demo.bundle.user.org.model.entity.UserPerson;
import com.liyunc.demo.bundle.user.org.model.entity.UserPersonalAccount;
import com.liyunc.demo.bundle.user.org.dao.repository.UserPersonalAccountRepository;
import com.liyunc.demo.bundle.user.org.dao.repository.UserPersonRepository;
import com.liyunc.demo.bundle.user.org.service.UserPersonalAccountService;
import com.liyunc.demo.comp.auth.AuthenticatedUser;
import com.liyunc.demo.comp.common.rest.request.PageRequest;
import com.liyunc.demo.comp.entity.base.RowStatus;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author liyuncong
 * @version 1.0
 * @file UserPersonalAccountServiceImpl.java
 * @brief UserPersonalAccountServiceImpl
 * @details UserPersonalAccountServiceImpl
 * @date 2022-04-01
 *
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                        NAME               DESCRIPTION
 * 2022-04-01                  liyuncong          Created
 */
@Log4j2
@Service
public class UserPersonalAccountServiceImpl implements UserPersonalAccountService {

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private UserPersonRepository personRepository;
    @Autowired
    private UserPersonConverter personConverter;
    @Autowired
    private UserPersonalAccountRepository accountRepository;
    @Autowired
    private UserPersonalAccountMapper accountMapper;

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Optional<PersonRegisterResponseDto> register(PersonRegisterRequestDto requestDto) {
        UserPerson userinfo = personConverter.fromRegisterDto(requestDto);
        UserPerson saveUser = personRepository.saveAndFlush(userinfo);
        UserPersonalAccount account = personConverter.fromRegisterDto(requestDto, passwordEncoder);
        account.setPerson(saveUser);
        UserPersonalAccount saveAccount = accountRepository.saveAndFlush(account);
        return Optional.of(personConverter.toRegisterResult(saveUser, saveAccount));
    }

    @Override
    public Optional<PersonRegisterResponseDto> managerCreatePerson(
        PersonManagerRegisterRequestDto requestDto) {
        return Optional.empty();
    }

    @Override
    public Optional<UserPersonalAccountDto> authenticate(
        String loginUsername, String loginPassword
    ) {
        Optional<UserPersonalAccount> result =
            accountRepository.findByLoginUsernameAndRowStatus(loginUsername, RowStatus.OK);
        if (result.isEmpty()) {
            return Optional.empty();
        }
        if (!passwordEncoder.matches(loginPassword, result.get().getLoginPassword())) {
            return Optional.empty();
        }
        return result.map(personConverter::fromEntity);
    }

    @Override
    public Optional<UserPersonalAccountDto> getCurrentLoginPersonInfo() {
        Optional<AuthenticatedUser<?>> result = AuthenticatedUser.currentUser();
        return result
            .map(item -> {
                Long userPersonalAccountId = Long.valueOf(item.getUserId());
                return personConverter.fromEntity(
                    accountRepository.getById(userPersonalAccountId)
                );
            });
    }

    @Override
    public Optional<UserPersonalAccountDto> updateAccountStatus(
        Long userPersonalAccountId, Integer status) {
        return Optional.empty();
    }

    @Override
    public Optional<UserPersonalAccountDto> resetPassword(
        PersonResetPasswordRequestDto requestDto) {
        return Optional.empty();
    }

    @Override
    public Optional<UserPersonalAccountDto> updatePersonInfo(PersonUpdateRequestDto requestDto) {
        return Optional.empty();
    }

    @Override
    public Optional<Pair<IPage<?>, List<UserPersonalAccountDto>>> searchUserPersonalAccounts(
        Long userPersonalAccountId, PageRequest pageRequest, String keyword
    ) {
        final int current = pageRequest.getPage();
        final int size = pageRequest.getSize();
        final String sort = pageRequest.getOrder();
        IPage<UserPersonalAccount> page = new Page<>(current, size);
        final List<UserPersonalAccount> result = accountMapper.findAll(page, sort, keyword);
        log.info(result);
        return Optional.of(Pair.of(
            page,
            result.stream().map(personConverter::fromEntity).collect(Collectors.toList())
        ));
    }
}
